package com.sybil.ot.controlador;

import com.sybil.ot.dominio.Factura;
import com.sybil.ot.dominio.Moneda;
import com.sybil.ot.dominio.OrdenTrabajo;
import com.sybil.ot.dominio.Pedido;
import com.sybil.ot.servicio.FlujoServicio;
import com.sybil.ot.servicio.MonedaServicio;
import com.sybil.ot.servicio.OrdenTrabajoService;
import com.sybil.ot.servicio.PedidoServicio;
import com.sybil.ot.servicio.ProveedorService;
import java.beans.PropertyEditorSupport;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/pedidos")
public class PedidoControlador {

   @Autowired
   private PedidoServicio pedidoServicio;
   @Autowired
   private ProveedorService proveedorService;
   @Autowired
   private MonedaServicio monedaServicio;
   @Autowired
   private OrdenTrabajoService ordenTrabajoService;
   @Autowired
   private FlujoServicio flujoServicio;

   @InitBinder
   public void binder(WebDataBinder binder) {
      binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
         @Override
         public void setAsText(String value) {
            try {
               setValue(new java.text.SimpleDateFormat("dd/MM/yyyy").parse(value));
            } catch (java.text.ParseException e) {
               setValue(null);
            }
         }

         @Override
         public String getAsText() {
            try {
               return new java.text.SimpleDateFormat("dd/MM/yyyy").format((Date) getValue());
            } catch (Exception e) {
               return "";
            }
         }
      });
   }

   @RequestMapping(method = RequestMethod.GET)
   public String pedidoLista(Model model) {
      model.addAttribute("pedidos", pedidoServicio.obtenerPedidos());
      return "pedido/listado";
   }

   @RequestMapping(params = "form", method = RequestMethod.GET)
   public String formularioPedidoNuevo(Model model) {
      Pedido pedido = new Pedido();
      pedido.setFecha(new java.util.Date());
      pedido.setFacturas(new ArrayList<Factura>());
      Factura factura = new Factura();
      factura.setPorcentajeIva(16.0f);
      factura.setTipoCambio(1.0);
      factura.setFechaFactura(pedido.getFecha());
      List<Moneda> monedas = monedaServicio.obtenerMonedas();
      factura.setMoneda(monedas.get(1) != null ? monedas.get(1) : null);
      pedido.getFacturas().add(factura);

      model.addAttribute("monedas", monedas);
      model.addAttribute("proveedores", proveedorService.obtenerProveedores());
      model.addAttribute("flujos", flujoServicio.obtenerFlujos());
//      model.addAttribute("ots", ordenTrabajoService.obtenerOrdenesTrabajo());
      model.addAttribute(pedido);
      return "pedido/nuevo";
   }

   @RequestMapping(params = "form", method = RequestMethod.POST)
   public String pedidoNuevo(@Valid @ModelAttribute Pedido pedido,
           BindingResult result, Model model,
           @RequestParam(required = false, value = "guarda_envia") String enviar,
           @RequestParam(required = false, value = "guarda") String guardar,
           @RequestParam(required = false, value = "agrega") String agrega,
           @RequestParam(required = false, value = "borra") String borra) {
      if (agrega != null) {
         Factura factura = new Factura();
         factura.setFechaFactura(pedido.getFecha());
         List<Moneda> monedas = monedaServicio.obtenerMonedas();
         factura.setMoneda(monedas.get(1) != null ? monedas.get(1) : null);
         factura.setPorcentajeIva(pedido.getFacturas().get(0).getPorcentajeIva());
         pedido.getFacturas().add(factura);

         model.addAttribute("monedas", monedas);
         model.addAttribute("proveedores", proveedorService.obtenerProveedores());
         model.addAttribute("flujos", flujoServicio.obtenerFlujos());
         return "pedido/nuevo";
      } else if (borra != null) {
         pedido.getFacturas().remove(Integer.parseInt(borra));
         List<Moneda> monedas = monedaServicio.obtenerMonedas();
         model.addAttribute("monedas", monedas);
         model.addAttribute("proveedores", proveedorService.obtenerProveedores());
         model.addAttribute("flujos", flujoServicio.obtenerFlujos());
         return "pedido/nuevo";
      } else {
         if (result.hasErrors()) {
            model.addAttribute("proveedores", proveedorService.obtenerProveedores());
            model.addAttribute("monedas", monedaServicio.obtenerMonedas());
            model.addAttribute("ots", ordenTrabajoService.obtenerOrdenesTrabajo());
            model.addAttribute("flujos", flujoServicio.obtenerFlujos());
            return "pedido/nuevo";
         } else {
            try {
               String usuarioActual = SecurityContextHolder.getContext().getAuthentication().getName();
               pedido.setUsuarioCreo(usuarioActual);
               if (guardar != null) {
                  pedidoServicio.guardar(pedido, false);
               } else if (enviar != null) {
                  pedidoServicio.guardar(pedido, true);
               }
            } catch (Exception e) {
               model.addAttribute("proveedores", proveedorService.obtenerProveedores());
               model.addAttribute("monedas", monedaServicio.obtenerMonedas());
//               model.addAttribute("ots", ordenTrabajoService.obtenerOrdenesTrabajo());
               model.addAttribute("flujos", flujoServicio.obtenerFlujos());
               model.addAttribute("error_bd", e.getMessage() + " \n" + e.toString());
               return "pedido/nuevo";
            }
            return "redirect:/pedidos";
         }
      }
   }

   @RequestMapping(value = "{numero}", params = {"serie", "ac"}, method = RequestMethod.GET)
   public String formularioPedidoEditar(@PathVariable("numero") int numero,
           @RequestParam(value = "serie") String serie, @RequestParam(value = "ac") String ac,
           Model model) {
      if ("e".equalsIgnoreCase(ac)) {
         Pedido pedido = pedidoServicio.obtenerPedido(serie, numero);
         model.addAttribute(pedido);
         return "pedido/editar";
      } else {
         pedidoServicio.eliminarPedido(serie, numero);
         return "redirect:/pedidos";
      }
   }

   @RequestMapping(value = "{numero}", params = {"serie", "ac"}, method = RequestMethod.POST)
   public String pedidoEditar(@Valid @ModelAttribute Pedido pedido,
           BindingResult result, Model model,
           @RequestParam(required = false, value = "guarda_envia") String enviar,
           @RequestParam(required = false, value = "guarda") String guardar) {
      if (result.hasErrors()) {
         model.addAttribute("proveedores", proveedorService.obtenerProveedores());
         model.addAttribute("monedas", monedaServicio.obtenerMonedas());
         model.addAttribute("ots", ordenTrabajoService.obtenerOrdenesTrabajo());
         return "pedido/editar";
      } else {
         String usuarioActual = SecurityContextHolder.getContext().getAuthentication().getName();
         pedido.setUsuarioModif(usuarioActual);
         if (guardar != null) {
            pedidoServicio.editar(pedido, false);
         } else if (enviar != null) {
            pedidoServicio.editar(pedido, true);
         }
         return "redirect:/pedidos";
      }
   }

   @RequestMapping(value = "/pdf", params = {"sp", "np"}, method = RequestMethod.GET)
   public void pdfOrdenTrabajo(
           @RequestParam(value = "sp") String serie,
           @RequestParam(value = "np") int numero,
           HttpServletResponse response) {
      try {
         String ruta = pedidoServicio.generarPDF(serie, numero);
         InputStream is = new FileInputStream(new File(ruta));
         IOUtils.copy(is, response.getOutputStream());
         is.close();
         response.setContentType("application/pdf");
         response.flushBuffer();
      } catch (IOException ex) {
//      throw new RuntimeException("IOError writing file to output stream");
      }
   }

   @RequestMapping(value = "/anexo", params = "ruta", method = RequestMethod.GET)
   public void anexoFactura(
           @RequestParam(value = "ruta") String ruta,
           HttpServletResponse response) {
      try {
         File fichero = new File(ruta);
         InputStream is = new FileInputStream(fichero);
         IOUtils.copy(is, response.getOutputStream());
         is.close();
         response.flushBuffer();
      } catch (IOException ex) {
//      throw new RuntimeException("IOError writing file to output stream");
      }
   }

   @RequestMapping(value = "/ots", params = {"np"}, method = RequestMethod.GET)
   public String obtenerOtsProveedor(@RequestParam(value = "np") String numeroProveedor, Model model) {
      List<OrdenTrabajo> ots = ordenTrabajoService.obtenerOrdenesTrabajoProveedor(numeroProveedor);
      model.addAttribute("ots", ots);
      return "pedido/ots_proveedor";
   }
}
